import { ComponentType } from "../component/Component";
import { System } from "./System";
import { Engine } from "../Engine";
import { Register } from "../register/Register";
import { EventType, Event } from "../event/index";
import { Buffer } from "../gpu/types/Buffer";
import { locations } from "../gpu/locations";
import {  getIndexType,debounce } from "../core/fun";
import { Pass } from "../component/post/Pass";
/**
 * @class
 * @extends w.system.System
 * @memberof w.system
 */
class RenderSystem extends System {
  constructor(opts = {}) {
    super(opts);
    this.requestId;
    this.event = new Event(EventType.FrameCompleted);
    // this.on(EventType.ShadowUpdate, this.shadowUpdate);
    this._shadowUpdate = debounce(this.shadowUpdate, this);//节流
    this.mode = "value";
    this.once=false;//是否立刻执行
    this.shadowBundles = []
    this.shadowPointBundles = []
  }
  run(event) {
    if (
      event.componentType === ComponentType.MeshRender || 
      event.componentType === ComponentType.Camera || //全局则触发值改变
      event.componentType === ComponentType.AmbientLight ||
      event.componentType === ComponentType.HemisLight ||
      event.componentType === ComponentType.PunctualLight ||
      event.componentType === ComponentType.EnviromentLight ||
      event.componentType === ComponentType.PostProcessing) {
      this.componentType=event.componentType
      if (event.mode == "layout") {
        this.mode = event.mode;
      }
      this.frame(); //mesh改变会触发值或结构改变
    }
  }
  frame() {
    if (this.requestId) {
      window.cancelAnimationFrame(this.requestId);
    }
    if(this.once){
      this.render();;
    }else{
      this.requestId = window.requestAnimationFrame(this.excute.bind(this));
    }
  }
  excute() {
    this.once=false;
    if (this.mode == "layout") {
      Engine.instance.checkAuth();//授权检验
      this.pack();
      this.mode = "value";
    }
    this.render();
    // if (!Engine.instance.inPick) {
    //   this.render();
    //   console.log("render");
    // }
  }
  async render() {

    // 获取meshRender
    Engine.instance.scene.getCamera().toGPU();
    // 精准灯光
    const punctualLightCom = Register.instance.manager(ComponentType.PunctualLight).get("x");
    punctualLightCom.toGPU();
    // 环境光
    const AmbientLightCom = Register.instance.manager(ComponentType.AmbientLight).get("x");
    AmbientLightCom?.toGPU();
    // 循环场景中值改变的mesh组件进行toGpu]
    const meshRednerCom = Register.instance.manager(ComponentType.MeshRender).get("x");
    const meshes = meshRednerCom.meshTask;
    for (let id of meshes) {
      const meshCom = Register.instance.manager(ComponentType.Mesh).get(id);
      if (meshCom) {
        meshCom.toGPU();
        let trans = this.getTrans(meshCom);
        if (trans) {
          trans.toGPU(meshCom);
        }
        meshes.delete(id);
      }
    }
    // 场景模型位置改变阴影重新生成
    if(this.componentType === ComponentType.MeshRender||this.componentType === ComponentType.PunctualLight){
      this.shadowUpdate()
      // let self=this
      // this._shadowUpdate()
    }
    //执行销毁任务
    // const destroyComs = [...Register.instance.manager(ComponentType.Destroy).components.values()];
    // for (let i = 0; i < destroyComs.length - 100; i++) {
    //   let groupid = destroyComs[i].getGroup()[0];
    //   if (!groupid) {
    //     continue;
    //   }
    //   let group = Register.instance.entityManager.get(groupid);
    //   if (group) {
    //     group.destroy(false);
    //   }
    // }
    //开始渲染
    let commandEncoder = Engine.instance.device.createCommandEncoder();
    const bundles = meshRednerCom.bundles;
    //获取后处理
    Pass.instance().reset();
    const postprocessing = Register.instance.manager(ComponentType.PostProcessing).get("x");
    let pass = this.getDescript();
    if (postprocessing.actives.length <= 0) {
      pass.colorAttachments[0].view = Engine.instance.context.getCurrentTexture().createView(); //渲染到屏幕上
    }
    const renderPass = commandEncoder.beginRenderPass(pass);
    // renderPass.setViewport(0,0,500,500,0,1);
    renderPass.executeBundles(bundles);
    renderPass.end();

    //有后处理
    for (let i = 0; i < postprocessing.actives.length; i++) {
      const effect = postprocessing.actives[i];
      effect.onRender(commandEncoder);
    }

    //提交指令
    Engine.instance.queue.submit([commandEncoder.finish()]);
    await Engine.instance.queue.onSubmittedWorkDone();
    this.publish(this.event);
  }
  getDescript() {
    if (this._descript) {
      if (
        this._descript.size[0] !== Engine.instance.size[0] ||
        this._descript.size[1] !== Engine.instance.size[1]
      ) {
        this._descript = null;
      }else{
        this._descript.colorAttachments[0].view=Pass.instance().writeAttach.view;
      }
    }
    if (!this._descript) {
      this._descript = {
        colorAttachments: [
          {
            view: Pass.instance().writeAttach.view,
            loadOp: "clear",
            clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
            storeOp: "store",
          },
        ],
        depthStencilAttachment: {
          view: Pass.instance().depthAttach.view,
          depthClearValue: 1.0,
          depthLoadOp: "clear",
          depthStoreOp: "store",
        },
      };
      if (Engine.instance.enableGbuffer) {
        this._descript.colorAttachments.push({
          label: "position",
          view: Pass.instance().postionTexture.view,
          loadOp: "clear",
          clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 0 },
          storeOp: "store",
        });
        this._descript.colorAttachments.push({
          label: "normal",
          view: Pass.instance().normalTexture.view,
          loadOp: "clear",
          clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 0 },
          storeOp: "store",
        });
      }
      if (Engine.instance.enablePick) {
        this._descript.colorAttachments.push({
          label: "pick",
          view: Pass.instance().pickAttach.view,
          loadOp: "clear",
          clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 0 },
          storeOp: "store",
        });
      }
      this._descript.size = Engine.instance.size;
    }
    return this._descript;
  }
  async pack() {
    // 获取场景
    const scene = Engine.instance.scene;
    this.scene = scene;
    // 获取meshRender
    const meshRednerCom = Register.instance.manager(ComponentType.MeshRender).get("x");
    if (!meshRednerCom) {
      return;
    }
    const punctualLightCom = Register.instance.manager(ComponentType.PunctualLight).get("x");
    punctualLightCom.toGPU();
    const lightCameraArray = punctualLightCom.lightCameraArray;
    if (Engine.instance.shadowEnable && lightCameraArray?.length > 0) {
      const shadowDepthTextureDest = Engine.instance.device.createTexture({
        format: "depth32float",
        size: { width: 2048*3, height: 2048*3, depthOrArrayLayers: lightCameraArray.length },
        dimension: "2d",
        usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING |
          GPUTextureUsage.COPY_SRC,
      });
      for (let index = 0; index < lightCameraArray.length; index++) {
        let transparentShadow = [], nonTransparentShadow = [];
        const lightCamerabuffer = lightCameraArray[index];
        this.recurveSceneShadow(scene, transparentShadow, nonTransparentShadow, lightCamerabuffer);
        const commandEncoder = Engine.instance.device.createCommandEncoder();
        this.singleDepthTexture = Engine.instance.device.createTexture({
          size: [2048*3, 2048*3],
          // size:  Engine.instance.size,
          usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST |
            GPUTextureUsage.COPY_SRC,
          format: "depth32float",
        });
        if(!this.singleDepthTexture.view){
          this.singleDepthTexture.view=this.singleDepthTexture.createView()
        }
        const shadowPassDescriptor = {
          colorAttachments: [],
          depthStencilAttachment: {
            view: this.singleDepthTexture.view,
            depthClearValue: 1.0,
            depthLoadOp: "clear",
            depthStoreOp: "store",
          },
        };
        const RenderPass = commandEncoder.beginRenderPass(shadowPassDescriptor);
        let bundles = [...nonTransparentShadow, ...transparentShadow]
        this.shadowBundles[index] = bundles
        RenderPass.executeBundles(bundles);
        RenderPass.end();
        if (bundles.length > 0) {
          commandEncoder.copyTextureToTexture(
            {
              texture: this.singleDepthTexture,
            },
            {
              texture: shadowDepthTextureDest,
              origin: { x: 0, y: 0, z: index },
            },
            {
              width: 2048*3,
              height: 2048*3,
            },
          );
          let cbf = commandEncoder.finish();
          Engine.instance.queue.submit([cbf]);
        }

      }
      if (!this.shadowDepthTexture) { this.isDiff = true }
      this.shadowDepthTexture = shadowDepthTextureDest;

    }
    const pointShadow = punctualLightCom.pointShadow
    if (Engine.instance.shadowEnable && pointShadow?.length > 0) {
      const pointShadowTexArray = Engine.instance.device.createTexture({
        format: "depth32float",
        size: { width: 2048*3, height: 2048*3, depthOrArrayLayers: pointShadow.length * 6 },
        dimension: "2d",
        usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING |
          GPUTextureUsage.COPY_SRC,
      });
      const indexBuffer = new Buffer({
        id: "ShadowPointIndex",
        name: "ShadowPointIndex",
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
        visibility: GPUShaderStage.VERTEX,
        type: "uniform",
        size: 4,
        data: new Uint32Array(1),
      });
     this.indexBuffer=indexBuffer
      let texArrIndex = 0
      for (let index = 0; index < pointShadow.length; index++) {
        let singleLightCamera = pointShadow[index]
        for (let i = 0; i < 6; i++) {
          indexBuffer.buffer(new Uint32Array([i]))
          let transparentShadow = [], nonTransparentShadow = [];
          this.recurveSceneShadowPoint(scene, transparentShadow, nonTransparentShadow, indexBuffer, singleLightCamera)
          const commandEncoder = Engine.instance.device.createCommandEncoder();
          // 
          this.singleDepthTexture = Engine.instance.device.createTexture({
            size: [2048*3, 2048*3],
            usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST |
              GPUTextureUsage.COPY_SRC,
            format: "depth32float",
          });
          this.singleColorTexture = Engine.instance.device.createTexture({
            label: "pointDepth",
            size: [2048*3, 2048*3],
            format: Engine.instance.format,
            mipLevelCount: 1,
            sampleCount: 1,
            usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC,
          });
          if(!this.singleDepthTexture.view){
            this.singleDepthTexture.view=this.singleDepthTexture.createView()
          }
          if(!this.singleColorTexture.view){
            this.singleColorTexture.view=this.singleColorTexture.createView()
          }
          const shadowPassDescriptor = {
            colorAttachments: [{
              view: this.singleColorTexture.view,
              loadOp: "clear",
              clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
              storeOp: "store",
            }],
            depthStencilAttachment: {
              view:  this.singleDepthTexture.view,
              depthClearValue: 1.0,
              depthLoadOp: "clear",
              depthStoreOp: "store",
            },
          };
          const RenderPass = commandEncoder.beginRenderPass(shadowPassDescriptor);
          let bundles = [...nonTransparentShadow, ...transparentShadow]
          if(this.shadowPointBundles[index]){
            this.shadowPointBundles[index][i] = bundles
          }else{
            this.shadowPointBundles[index]=[]
            this.shadowPointBundles[index][i] = bundles
          }
          
          RenderPass.executeBundles(bundles);
          RenderPass.end();
          if (bundles.length > 0) {
            commandEncoder.copyTextureToTexture(
              {
                texture: this.singleDepthTexture,
              },
              {
                texture: pointShadowTexArray,
                origin: { x: 0, y: 0, z: texArrIndex },
              },
              {
                width: 2048*3,
                height: 2048*3,
              },
            );
            let cbf = commandEncoder.finish();
            Engine.instance.queue.submit([cbf]);
          }
          texArrIndex++
        }
      }
      if (!this.pointShadowTex) { this.isDiff = true }
      this.pointShadowTex = pointShadowTexArray
    }
    let transparent = [],
      nonTransparent = [];
    meshRednerCom.bundles = [];
    // 如果是阴影开启，主渲染需要增加this.shadowMaps与灯光相机数组
    this.recurveScene(scene, transparent, nonTransparent);
    meshRednerCom.bundles = [...nonTransparent, ...transparent];
    // console.log(meshRednerCom.bundles,"scene");
  }

  getTrans(mesh) {
    let trans;
    const eid = [...mesh.eids][0];
    if (eid) {
      const entity = Register.instance.entityManager.get(eid);
      if (entity) {
        trans = entity.getComponent(ComponentType.Trans);
      }
    }
    return trans;
  }
  recurveScene(group, transparent, nonTransparent) {
    // 处理当前组的原型数据
    const __name = group.name;
    const meshRednerCom = Register.instance.manager(ComponentType.MeshRender).get("x");
    const classify = meshRednerCom.groups;
    if (!group.visibility) {
      //组可见性为false，则不打包
      return;
    }
    const arcObject = classify.get(group.id);
    if (!arcObject) {
      return;
    }
    const archetypes = arcObject.archetypes;
    if (archetypes && archetypes.size > 0) {
      // 循环原型;hash是由参数的name组成color、map等
      for (let [key, archetype] of archetypes) {
        if (!archetype.state || this.isDiff) {//如果state等于false,或者阴影之前没有创建，都需要重新打包，创建pieline的layout
          let colorFormats = []
          colorFormats.push(Engine.instance.format)
          if (Engine.instance.enableGbuffer) {
            colorFormats.push('rgba32float')
            colorFormats.push('rgba16float')
          }
          if (Engine.instance.enablePick) {
            colorFormats.push(Engine.instance.format)
          }
          const renderBundleEncoder = Engine.instance.device.createRenderBundleEncoder({
            colorFormats: colorFormats,
            sampleCount: 1,
            depthStencilFormat: ["depth24plus"],
          });
          const meshes = archetype.meshes;
          let firstMeshId = [...meshes][0]; //mesh 组件id
          // 根据组件id找组件
          const meshCom = Register.instance.manager(ComponentType.Mesh).get(firstMeshId);
          meshCom?.toGPU();
          let trans = this.getTrans(meshCom);
          if (!trans) {
            continue;
          }
          trans.toGPU(meshCom);
          // 相机
          let entriesGroup = [],
            entriesLayout = [],
            entriesName=[],
            def = {};
          const cameraCom = this.scene.getCamera();
          cameraCom?.toGPU();
          if (meshCom.geometry.cameraView === "all") {
            //获取相机的参数
            const cameraParams = cameraCom.getAllParams();
            for (let index = 0; index < cameraParams.length; index++) {
              const element = cameraParams[index];
              entriesLayout.push(element.gpu.layout);
              entriesGroup.push(element.gpu.entry);
              entriesName.push(element.name);
              def[element.name] = element.value;
            }
          }

          // 精准灯光
          const punctualLightCom = Register.instance.manager(ComponentType.PunctualLight).get("x");
          punctualLightCom?.toGPU();
          const lightCameraArray = punctualLightCom.lightCameraArray;
          const pointShadow = punctualLightCom.pointShadow;
          // 环境光
          const AmbientLightCom = Register.instance.manager(ComponentType.AmbientLight).get("x");
          AmbientLightCom?.toGPU();
          const EnviromentLightCom = Register.instance
            .manager(ComponentType.EnviromentLight)
            .get("x");
          EnviromentLightCom?.toGPU();
          if (!meshCom.material.defuseLight) {
            if (meshCom.material.materialType === "StandardMaterial") {
              const EnviromentLightParams = EnviromentLightCom.getAllParams();
              for (let index = 0; index < EnviromentLightParams.length; index++) {
                const element = EnviromentLightParams[index];
                entriesLayout.push(element.gpu.layout);
                entriesGroup.push(element.gpu.entry);
                entriesName.push(element.name);
                def[element.name] = element.value;
              }
            }
            const punctualLightParams = punctualLightCom.getAllParams();
            for (let index = 0; index < punctualLightParams.length; index++) {
              const element = punctualLightParams[index];
              if (element instanceof Buffer) {
                entriesLayout.push(element.gpu.layout);
                entriesGroup.push(element.gpu.entry);
                entriesName.push(element.name);
              }
              def[element.name] = element.value;
            }
            const AmbientLightParams = AmbientLightCom.getAllParams();
            for (let index = 0; index < AmbientLightParams.length; index++) {
              const element = AmbientLightParams[index];
              entriesLayout.push(element.gpu.layout);
              entriesGroup.push(element.gpu.entry);
              entriesName.push(element.name);
              def[element.name] = element.value;
            }
            if (Engine.instance.shadowEnable && lightCameraArray?.length > 0) {
              let showMapLayout = {
                binding: locations.ShadowMap[1],
                visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
                texture: {
                  sampleType: 'depth',
                  viewDimension: "2d-array"
                  // viewDimension:"2d"
                },
              }
              entriesLayout.push(showMapLayout)
              let showMapSample = {
                binding: locations.ShadowSampler[1],
                visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
                sampler: {
                  type: 'filtering',
                  // type: 'comparison',
                },
              }
              entriesLayout.push(showMapSample)
              const gpuSampler = Engine.instance.device.createSampler({
                magFilter: 'linear',
                minFilter: 'linear',
                addressModeU: "clamp-to-edge",
                addressModeV: "clamp-to-edge",
                addressModeW: "clamp-to-edge"
              });
              // const gpuSampler = Engine.instance.device.createSampler({
              //   compare: 'less',
              // });
              let showMapEntry = {
                binding: locations.ShadowMap[1],
                // resource: shadowDepthTextureDest,
                resource: this.shadowDepthTexture.createView({ dimension: `2d-array` }),
                // resource: shadowDepthTextureDest.createView({ dimension: `2d`}),
              }
              entriesGroup.push(showMapEntry)
              entriesName.push("ShadowMap");
              let showMapSampleEntry = {
                binding: locations.ShadowSampler[1],
                resource: gpuSampler
              }
              entriesGroup.push(showMapSampleEntry)
              def["ShadowMap"] = true
            }
            if (Engine.instance.shadowEnable && pointShadow?.length > 0) {
              let showMapLayout = {
                binding: locations.ShadowMapPoint[1],
                visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
                texture: {
                  sampleType: 'depth',
                  viewDimension: "cube-array"
                },
              }
              entriesLayout.push(showMapLayout)
              let showMapSample = {
                binding: locations.ShadowSamplerPoint[1],
                visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
                sampler: {
                  type: 'filtering',
                },
              }
              entriesLayout.push(showMapSample)
              const gpuSampler = Engine.instance.device.createSampler({
                magFilter: 'linear',
                minFilter: 'linear',
                addressModeU: "clamp-to-edge",
                addressModeV: "clamp-to-edge",
                addressModeW: "clamp-to-edge"
              });
              let showMapEntry = {
                binding: locations.ShadowMapPoint[1],
                resource: this.pointShadowTex.createView({ dimension: `cube-array` }),
              }
              entriesGroup.push(showMapEntry)
              entriesName.push("pointShadow")
              let showMapSampleEntry = {
                binding: locations.ShadowSamplerPoint[1],
                resource: gpuSampler
              }
              entriesGroup.push(showMapSampleEntry)
              def["pointShadow"] = true
            }
          } else {
            const envInten = EnviromentLightCom.getParam("environmenIntensity")
            entriesLayout.push(envInten.gpu.layout);
            entriesGroup.push(envInten.gpu.entry);
            entriesName.push(envInten.nam)
            def[envInten.name] = envInten.value;
          }
          let newHash=entriesName.join()
          let uniformsBindGroupLayout = [];
          if(this.grouplayouts0?.hash!=newHash){
            this. grouplayouts0 = Engine.instance.device.createBindGroupLayout({
              label: "layout" + 0,
              entries: entriesLayout,
            });
            this.grouplayouts0.hash=newHash
            this.  bindGroup0 = Engine.instance.device.createBindGroup({
              label: "bindGroup" + 0,
              layout:this. grouplayouts0,
              entries: entriesGroup,
            });
          }

          renderBundleEncoder.setBindGroup(0, this.bindGroup0);
          uniformsBindGroupLayout.push(this.grouplayouts0);
          if (trans.grouplayouts1) uniformsBindGroupLayout.push(trans.grouplayouts1);
          if (meshCom.grouplayouts2) uniformsBindGroupLayout.push(meshCom.grouplayouts2);
          if (meshCom.grouplayouts3) uniformsBindGroupLayout.push(meshCom.grouplayouts3);
          def = { ...def, ...meshCom.defs, ...trans.defs };
          // gBuffer
          if (Engine.instance.enableGbuffer) {
            def.gBuffer = true
          }
          // logarithmicDepth
          if (Engine.instance.logarithmicDepth) {
            def.logarithmicDepth = cameraCom.farLog
          }
          if (Engine.instance.enablePick) {//判断是否开启拾取
            def.enablePick = true;
          }
          // 创建pipeline
          const pipeManager = Register.instance.pipeManager;
          const pipeline = pipeManager.get(archetype, {
            uniformsBindGroupLayout: uniformsBindGroupLayout,
            config: meshCom.config,
            _defs: def,
            vetexLayout: meshCom.vertexBuffer,
            isDiff: this.isDiff
          });
          renderBundleEncoder.setPipeline(pipeline);

          //  循环渲染组件mesh

          for (let id of meshes) {
            const meshCom = Register.instance.manager(ComponentType.Mesh).get(id);
            if (meshCom) {
              meshCom.toGPU();
              let trans = this.getTrans(meshCom);
              if (!trans) {
                continue;
              }
              trans.toGPU(meshCom);
              if (trans.bindGroup1) renderBundleEncoder.setBindGroup(1, trans.bindGroup1);
              if (meshCom.bindGroup2) renderBundleEncoder.setBindGroup(2, meshCom.bindGroup2);
              if (meshCom.bindGroup3) renderBundleEncoder.setBindGroup(3, meshCom.bindGroup3);
              let instanceCount = trans.config["instanceCount"];
              let positionParam = null,
                indices = null;
              let soltIndex = 0;
              for (let index = 0; index < meshCom.geometryParams.length; index++) {
                const geometryParam = meshCom.geometryParams[index];
                if (geometryParam.name === "indices") {
                  const indexType = getIndexType(geometryParam.bufferDataType);
                  renderBundleEncoder.setIndexBuffer(geometryParam.gpu.buffer, indexType);
                  indices = geometryParam;
                } else {
                  if (geometryParam.name === "position") {
                    //如果是position buffer需要在后面draw的时候设置数量
                    positionParam = geometryParam;
                    renderBundleEncoder.setVertexBuffer(soltIndex, geometryParam.gpu.buffer);
                    soltIndex++;
                  } else {
                    renderBundleEncoder.setVertexBuffer(soltIndex, geometryParam.gpu.buffer);
                    soltIndex++;
                  }
                }
              }
              // 如果存在索引需要单独设置buffer
              if (indices) {
                renderBundleEncoder.drawIndexed(indices.length, instanceCount);
              } else {
                if(positionParam.stepMode==="instance"){
                  renderBundleEncoder.draw(
                    6,
                    positionParam.length / positionParam.itemLength
                  );
                }else{
                  renderBundleEncoder.draw(
                    positionParam.length / positionParam.itemLength,
                    instanceCount
                  );
                }
              }
            }
          }
          let bundle = renderBundleEncoder.finish();
          bundle.label = key;
          bundle.name = __name;
          bundle.transparent = meshCom.config.transparent;
          if (meshCom.config.transparent) {
            transparent.push(bundle);
          } else {
            nonTransparent.push(bundle);
          }
          // meshRednerCom.bundles.push(bundle)
          archetype.bundle = bundle;
          archetype.state = true;
        } else {
          if (archetype.bundle.transparent) {
            transparent.push(archetype.bundle);
          } else {
            nonTransparent.push(archetype.bundle);
          }
          // meshRednerCom.bundles.push(archetype.bundle)
        }
      }
    }
    // 如果存在子孩子递归处理
    if (group.children && group.children.length > 0) {
      for (let index = 0; index < group.children.length; index++) {
        const groupID = group.children[index];
        let childgroup = Register.instance.entityManager.get(groupID);
        if (childgroup) {
          this.recurveScene(childgroup, transparent, nonTransparent);
        } else {
          continue;
        }
      }
    }
  }
  async recurveSceneShadow(group, transparent, nonTransparent, lightCamerabuffer) {
    // 处理当前组的原型数据
    const __name = group.name;
    const meshRednerCom = Register.instance.manager(ComponentType.MeshRender).get("x");
    const classify = meshRednerCom.groups;
    if (!group.visibility) {
      //组可见性为false，则不打包
      return;
    }
    const arcObject = classify.get(group.id);
    if (!arcObject) {
      return;
    }
    const archetypes = arcObject.archetypes;
    if (archetypes && archetypes.size > 0) {
      // 循环原型;hash是由参数的name组成color、map等
      for (let [key, archetype] of archetypes) {
        if (!archetype.stateShadow) {
          if (archetype.id.includes("SkyboxGeometry")) {
            continue;
          }
          const renderBundleEncoder = Engine.instance.device.createRenderBundleEncoder({
            // colorFormats: [Engine.instance.format],
            colorFormats: [],
            depthStencilFormat: ["depth32float"],
            sampleCount: 1,
          });
          const meshes = archetype.meshes;
          let firstMeshId = [...meshes][0]; //mesh 组件id
          // 根据组件id找组件
          const meshComFirst = Register.instance.manager(ComponentType.Mesh).get(firstMeshId);
          meshComFirst?.toGPU();
          const receiveShadow= meshComFirst.material.getParam("receiveShadow").value
          if(!receiveShadow){continue}
          let trans = this.getTrans(meshComFirst);
          trans.toGPU(meshComFirst);
          let entriesGroup = [],
            entriesLayout = [],
            def = {};
          // 精准灯光
          const punctualLightCom = Register.instance.manager(ComponentType.PunctualLight).get("x");
          punctualLightCom?.toGPU();
          entriesLayout.push(lightCamerabuffer.gpu.layout);
          entriesGroup.push(lightCamerabuffer.gpu.entry);
          def[lightCamerabuffer.name] = lightCamerabuffer.value;
          let uniformsBindGroupLayout = [];
          if(this.shadowgrouplayouts0?.def!=def){
            this.shadowgrouplayouts0 = Engine.instance.device.createBindGroupLayout({
              label: "layout" + 0,
              entries: entriesLayout,
            });
           this.shadowgrouplayouts0.def=def
            this.shadowbindGroup0 = Engine.instance.device.createBindGroup({
              label: "bindGroup" + 0,
              layout: this.shadowgrouplayouts0,
              entries: entriesGroup,
            });
          }
          renderBundleEncoder.setBindGroup(0, this.shadowbindGroup0);
          uniformsBindGroupLayout.push(this.shadowgrouplayouts0);
          if (trans.grouplayouts1) uniformsBindGroupLayout.push(trans.grouplayouts1);
          let defs = { ...def, ...trans.defs };
          // 获取顶点着色器
          const positionParam = meshComFirst.geometry.getParam("position");
          var vertexBuffer = [positionParam.gpu.layout];
          const vertexShader = Engine.instance.res.getShader("VertexShadow", defs);
          const shadowPipeline = Engine.instance.device.createRenderPipeline({
            label: "shadowPipeline",
            layout: Engine.instance.device.createPipelineLayout({
              bindGroupLayouts: uniformsBindGroupLayout,
            }),
            vertex: {
              module: Engine.instance.device.createShaderModule({
                code: vertexShader,
              }),
              entryPoint: "main",
              buffers: vertexBuffer,
            },
            depthStencil: {
              depthWriteEnabled: true,
              depthCompare: 'less',
              format: 'depth32float',
            },
            primitive: {
              topology: 'triangle-list',
              cullMode: 'none',
            },
          });
          renderBundleEncoder.setPipeline(shadowPipeline);
          //  循环渲染组件mesh

          for (let id of meshes) {
            const meshCom = Register.instance.manager(ComponentType.Mesh).get(id);
            if (meshCom) {
              meshCom.toGPU();
              let trans = this.getTrans(meshCom);
              if (!trans) {
                continue;
              }
              trans.toGPU(meshCom);
              if (trans.bindGroup1) renderBundleEncoder.setBindGroup(1, trans.bindGroup1);
              let instanceCount = trans.config["instanceCount"];
              const positionParam = meshCom.geometry.getParam("position");
              const indicesParam = meshCom.geometry.getParam("indices");
              if (indicesParam) {
                const indexType = getIndexType(indicesParam.bufferDataType);
                renderBundleEncoder.setIndexBuffer(indicesParam.gpu.buffer, indexType);
              }
              renderBundleEncoder.setVertexBuffer(0, positionParam.gpu.buffer);

              // 如果存在索引需要单独设置buffer
              if (indicesParam) {
                renderBundleEncoder.drawIndexed(indicesParam.length, instanceCount);
              } else {
                if(positionParam.stepMode==="instance"){
                  renderBundleEncoder.draw(
                    6,
                    positionParam.length / positionParam.itemLength
                  );
                }else{
                  renderBundleEncoder.draw(
                    positionParam.length / positionParam.itemLength,
                    instanceCount
                  );
                }
              }
            }
          }
          let bundleShadow = renderBundleEncoder.finish();
          bundleShadow.shadowLabel = key
          bundleShadow.transparent = meshComFirst.config.transparent;
          if (meshComFirst.config.transparent) {
            transparent.push(bundleShadow);
          } else {
            nonTransparent.push(bundleShadow);
          }
          archetype.bundleShadow = bundleShadow;
          archetype.stateShadow = true;
        } else {
          if (archetype.bundleShadow.transparent) {
            transparent.push(archetype.bundleShadow);
          } else {
            nonTransparent.push(archetype.bundleShadow);
          }
        }
      }
    }
    // 如果存在子孩子递归处理
    if (group.children && group.children.length > 0) {
      for (let index = 0; index < group.children.length; index++) {
        const groupID = group.children[index];
        let childgroup = Register.instance.entityManager.get(groupID);
        if (childgroup) {
          this.recurveSceneShadow(childgroup, transparent, nonTransparent, lightCamerabuffer);
        } else {
          continue;
        }
      }
    }
  }
  async recurveSceneShadowPoint(group, transparent, nonTransparent, indexBuffer, singleLightCamera) {
    // 处理当前组的原型数据
    const __name = group.name;
    const meshRednerCom = Register.instance.manager(ComponentType.MeshRender).get("x");
    const classify = meshRednerCom.groups;
    if (!group.visibility) {
      //组可见性为false，则不打包
      return;
    }
    const arcObject = classify.get(group.id);
    if (!arcObject) {
      return;
    }
    const archetypes = arcObject.archetypes;
    if (archetypes && archetypes.size > 0) {
      // 循环原型;hash是由参数的name组成color、map等
      for (let [key, archetype] of archetypes) {
        // if (!archetype.stateShadowPoint) {//
        if (archetype.id.includes("SkyboxGeometry")) {
          continue;
        }
        const renderBundleEncoder = Engine.instance.device.createRenderBundleEncoder({
          colorFormats: [Engine.instance.format],
          depthStencilFormat: ["depth32float"],
          sampleCount: 1,
        });
        const meshes = archetype.meshes;
        let firstMeshId = [...meshes][0]; //mesh 组件id
        // 根据组件id找组件
        const meshComFirst = Register.instance.manager(ComponentType.Mesh).get(firstMeshId);
        meshComFirst?.toGPU();
        const receiveShadow= meshComFirst.material.getParam("receiveShadow").value
        if(!receiveShadow){continue}
        let trans = this.getTrans(meshComFirst);
        trans.toGPU(meshComFirst);
        let entriesGroup = [],
          entriesLayout = [],
          def = {};
        // 精准灯光
        // const punctualLightCom = Register.instance.manager(ComponentType.PunctualLight).get("x");
        // punctualLightCom?.toGPU();
        entriesLayout.push(indexBuffer.gpu.layout);
        entriesGroup.push(indexBuffer.gpu.entry);
        def[indexBuffer.name] = indexBuffer.value;

        entriesLayout.push(singleLightCamera.gpu.layout);
        entriesGroup.push(singleLightCamera.gpu.entry);
        def[singleLightCamera.name] = singleLightCamera.value;
        let uniformsBindGroupLayout = [];
        const grouplayouts0 = Engine.instance.device.createBindGroupLayout({
          label: "layout" + 0,
          entries: entriesLayout,
        });
        let bindGroup0 = Engine.instance.device.createBindGroup({
          label: "bindGroup" + 0,
          layout: grouplayouts0,
          entries: entriesGroup,
        });
        renderBundleEncoder.setBindGroup(0, bindGroup0);
        uniformsBindGroupLayout.push(grouplayouts0);
        if (trans.grouplayouts1) uniformsBindGroupLayout.push(trans.grouplayouts1);
        def = { ...def, ...trans.defs };
        // 获取顶点着色器
        const positionParam = meshComFirst.geometry.getParam("position");
        var vertexBuffer = [positionParam.gpu.layout];
        const vertexShader = Engine.instance.res.getShader("PointShadowVertex", def);
        const fragShader = Engine.instance.res.getShader("PointShadowFrag", def);
        const shadowPipeline = Engine.instance.device.createRenderPipeline({
          layout: Engine.instance.device.createPipelineLayout({
            bindGroupLayouts: uniformsBindGroupLayout,
          }),
          vertex: {
            module: Engine.instance.device.createShaderModule({
              code: vertexShader,
            }),
            entryPoint: "main",
            buffers: vertexBuffer,
          },
          fragment: {
            module: Engine.instance.device.createShaderModule({
              code: fragShader,
            }),
            entryPoint: 'main',
            targets: [
              {
                format: Engine.instance.format,
              },
            ],
          },
          depthStencil: {
            depthWriteEnabled: true,
            depthCompare: 'less',
            format: 'depth32float',
          },
          primitive: {
            topology: 'triangle-list',
            cullMode: 'none',
          },
        });
        renderBundleEncoder.setPipeline(shadowPipeline);
        //  循环渲染组件mesh

        for (let id of meshes) {
          const meshCom = Register.instance.manager(ComponentType.Mesh).get(id);
          if (meshCom) {
            meshCom.toGPU();
            let trans = this.getTrans(meshCom);
            if (!trans) {
              continue;
            }
            trans.toGPU(meshCom);
            if (trans.bindGroup1) renderBundleEncoder.setBindGroup(1, trans.bindGroup1);
            let instanceCount = trans.config["instanceCount"];
            const positionParam = meshCom.geometry.getParam("position");
            const indicesParam = meshCom.geometry.getParam("indices");
            if (indicesParam) {
              const indexType = getIndexType(indicesParam.bufferDataType);
              renderBundleEncoder.setIndexBuffer(indicesParam.gpu.buffer, indexType);
            }
            renderBundleEncoder.setVertexBuffer(0, positionParam.gpu.buffer);

            // 如果存在索引需要单独设置buffer
            if (indicesParam) {
              renderBundleEncoder.drawIndexed(indicesParam.length, instanceCount);
            } else {
              if(positionParam.stepMode==="instance"){
                renderBundleEncoder.draw(
                  6,
                  positionParam.length / positionParam.itemLength
                );
              }else{
                renderBundleEncoder.draw(
                  positionParam.length / positionParam.itemLength,
                  instanceCount
                );
              }
            }
          }
        }
        let bundlePointShadow = renderBundleEncoder.finish();
        bundlePointShadow.shadowLabel = key
        bundlePointShadow.transparent = meshComFirst.config.transparent;
        if (meshComFirst.config.transparent) {
          transparent.push(bundlePointShadow);
        } else {
          nonTransparent.push(bundlePointShadow);
        }
        archetype.bundlePointShadow = bundlePointShadow;
        archetype.stateShadowPoint = true;
        // } else {
        //   if (archetype.bundlePointShadow.transparent) {
        //     transparent.push(archetype.bundlePointShadow);
        //   } else {
        //     nonTransparent.push(archetype.bundlePointShadow);
        //   }
        // }
      }
    }
    // 如果存在子孩子递归处理
    if (group.children && group.children.length > 0) {
      for (let index = 0; index < group.children.length; index++) {
        const groupID = group.children[index];
        let childgroup = Register.instance.entityManager.get(groupID);
        if (childgroup) {
          this.recurveSceneShadowPoint(childgroup, transparent, nonTransparent, indexBuffer, singleLightCamera);
        } else {
          continue;
        }
      }
    }
  }
  shadowUpdate() {
    // 精准灯光
    const punctualLightCom = Register.instance.manager(ComponentType.PunctualLight).get("x");
    punctualLightCom.toGPU();
    const lightCameraArray = punctualLightCom.lightCameraArray;
    if (Engine.instance.shadowEnable && lightCameraArray?.length > 0 && this.shadowDepthTexture) {
      for (let index = 0; index < lightCameraArray.length; index++) {
        const commandEncoder = Engine.instance.device.createCommandEncoder();
        // const shadowDepthTexture = Engine.instance.device.createTexture({
        //   size: [2048*3, 2048*3],
        //   // size:  Engine.instance.size,
        //   usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST |
        //     GPUTextureUsage.COPY_SRC,
        //   format: "depth32float",
        // });
        // const shadowDepthView = shadowDepthTexture.createView();
        const shadowPassDescriptor = {
          colorAttachments: [],
          depthStencilAttachment: {
            view: this.singleDepthTexture.view,
            depthClearValue: 1.0,
            depthLoadOp: "clear",
            depthStoreOp: "store",
          },
        };
        const RenderPass = commandEncoder.beginRenderPass(shadowPassDescriptor);
        let bundles = this.shadowBundles[index]
        RenderPass.executeBundles(bundles);
        RenderPass.end();
        if (bundles.length > 0) {
          commandEncoder.copyTextureToTexture(
            {
              texture: this.singleDepthTexture,
            },
            {
              texture: this.shadowDepthTexture,
              origin: { x: 0, y: 0, z: index },
            },
            {
              width: 2048*3,
              height: 2048*3,
            },
          );
          let cbf = commandEncoder.finish();
          Engine.instance.queue.submit([cbf]);
        }
      }
    }

    const pointShadow = punctualLightCom.pointShadow
    if (Engine.instance.shadowEnable && pointShadow?.length > 0 && this.pointShadowTex) {
      let texArrIndex = 0
      for (let index = 0; index < pointShadow.length; index++) {
        for (let i = 0; i < 6; i++) {
          this.indexBuffer.buffer(new Uint32Array([i]))
          const commandEncoder = Engine.instance.device.createCommandEncoder();
          // const shadowDepthTexture = Engine.instance.device.createTexture({
          //   size: [2048*3, 2048*3],
          //   usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST |
          //     GPUTextureUsage.COPY_SRC,
          //   format: "depth32float",
          // });
          // const colorTexture = Engine.instance.device.createTexture({
          //   label: "pointDepth",
          //   size: [2048*3, 2048*3],
          //   format: Engine.instance.format,
          //   mipLevelCount: 1,
          //   sampleCount: 1,
          //   usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC,
          // });
          // const shadowDepthView = shadowDepthTexture.createView();
          // const colorTextureView = colorTexture.createView();
          const shadowPassDescriptor = {
            colorAttachments: [{
              view: this.singleColorTexture.view,
              loadOp: "clear",
              clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
              storeOp: "store",
            }],
            depthStencilAttachment: {
              view: this.singleDepthTexture.view,
              depthClearValue: 1.0,
              depthLoadOp: "clear",
              depthStoreOp: "store",
            },
          };
          const RenderPass = commandEncoder.beginRenderPass(shadowPassDescriptor);
          let bundles = this.shadowPointBundles[index][i]
          RenderPass.executeBundles(bundles);
          RenderPass.end();
          if (bundles.length > 0) {
            commandEncoder.copyTextureToTexture(
              {
                texture: this.singleDepthTexture,
              },
              {
                texture: this.pointShadowTex,
                origin: { x: 0, y: 0, z: texArrIndex },
              },
              {
                width: 2048*3,
                height: 2048*3,
              },
            );
            let cbf = commandEncoder.finish();
            Engine.instance.queue.submit([cbf]);
          }
          texArrIndex++
        }
      }
    }

  }
}
export { RenderSystem };

